
#ifndef _ARBOLBMAS_H_
#define _ARBOLBMAS_H_

#include "Interno.h"
#include "Hoja.h"
#include "Funciones/ManejadorDeNodos.h"
#include "Funciones/Configuracion.h"
#include "../Comunes/Entidades/RecordTermino.h"
#include "../Comunes/Constantes.h"
#include "../Persistencia/Persistor.h"
#include "../Exceptions/RecordDuplicatedException.h"

using namespace std;



class ArbolBMas {

	friend class Nodo;
	friend class Interno;
	friend class Hoja;

private:

	Nodo* raiz;
	string path_file;
	int contador_de_nodos;
	int primeraHoja;

	long block_Size;
	unsigned int control_Data_Size;

	ManejadorDeNodos* manejo_Nodos;
	Configuracion* datos_Configuracion;

	void inicializar_raiz();
	Hoja* obtener_Hoja();
	Interno* obtener_Nodo_Interno(int nivel);
	int obtener_Posicion_Insercion(Nodo *nodo, string termino);
	int obtener_IdNodo();
	bool insertar_Recursivo(Nodo* nodo_actual,  RecordTermino * registro, string & new_key_root, Nodo** new_node);
	int insertar_en_hoja(Hoja* nodo_actual, RecordTermino * registro);
	RecordTermino* buscar_Recursivo(string termino, Nodo* nodo);
	void toString(Nodo* nodo, int tab, ofstream& fo);
	void toString_listado(Nodo* nodo, ofstream& file_list);
	void guardar_Nodo_en_Bloque(Nodo* nodo);
	Nodo* obtener_Nodo_desde_Bloque(int id_Nodo);
	void liberar_Memoria_Nodo(Nodo* nodo);
	void quitar_FrontCoding_Nodo (Nodo ** nodo);
	void quitar_FrontCoding_Hoja (Hoja ** nodo);
	void aplicar_FrontCoding_Hoja(Hoja** hoja_actual);
	void aplicar_FrontCoding(Nodo** nodo);
	void split_Nodo_Interno(Interno* interno_actual, string & new_key_root, Nodo** new_interno, int nueva_posicion);
	void split_Hoja(Hoja* n_hoja, string & clave_promovida, Nodo** nueva_hoja);
	void inicializar_archivos_de_bloques(string ruta);
	void serealizar_Configuracion();
	void deserealizar_Configuracion();

public:
	ArbolBMas();
	ArbolBMas(std::string ruta_archivo, unsigned int M);
	~ArbolBMas();
	bool insertar(RecordTermino * registro);
	//Busca un termino dentro del arbol y devuelve el registro que lo contiene,
	//sino lo encuentra devuelve el proximo elemento mas grande.
	RecordTermino* buscar(string clave);
	bool es_nula_la_raiz (){
		return (raiz==NULL);
	}
	//Guarda los terminos que tiene el registro en forma ordenada en un archivo de texto
	void EscribirListadoOrdenado();
	void MostrarArbol ();

};

#endif // _ARBOLBMAS_H_
